/**
 * Copyright (c) 2007, Blue Hole Software. All rights reserved.
 * Code licensed under the Apache 2.0 License:
 * http://www.apache.org/licenses/
 */
package org.bhf.providers.security.authentication;

import org.bhf.security.common.LoginID;

import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;

/**
 * Localization support for this package.  All localization should go through
 * this class and use the trinkets specified by this class.  The messages
 * MUST be in a set of resource bundles in this package with the root
 * name of Localization.
 * <p>
 * All methods are guaranteed not to throw an exception and produce some
 * form of non-null message.  The form of the message produced under error
 * conditions, such as a missing localization resource, is not defined
 * except that it will include the trinket itself and be readable in
 * English.
 */
final class Localize
{
    //
    // Package
    //

    static String       incompatible( final String required, final String actual )
    {
        return localize( "message.incompatible", new String[] { required, actual } );
    }

    /**
     * Returns a message indicating that the old and new passwords are the same.
     *
     * @return a message indicating that the old and new passwords are the same
     */
    static String       samePassword()
    {
        return localize( "message.password.same" );
    }

    /**
     * Returns a message indicating that the account for the Login ID
     * has been disabled.
     *
     * @param loginID the Login ID whose account has been disabled.
     * @return a message indicating that the account has been disabled.
     */
    static String       accountDisabled( final LoginID loginID )
    {
        return localize( "account.disabled", loginID.getID() );
    }

    /**
     * Returns a message indicating that the account for the Login ID
     * is on hold.
     *
     * @param loginID the Login ID whose account has been disabled.
     * @param minutes Hold in minutes
     * @return a message indicating that the account has been disabled.
     */
    static String       accountOnHold( final LoginID loginID, final int minutes )
    {
        return localize( "account.hold", minutes );
    }

    /**
     * Returns a localized message indicating that the specified Login ID
     * does not exist.
     *
     * @param loginID the Login ID that does not exist.
     * @return a message indicating that the specified Login ID does not exist.
     */
    static String       noSuchUser( final LoginID loginID )
    {
        return localize( "no.such.user", loginID.getID() );
    }

    /**
     * Returns a localized message indicating that a user
     * has successfully authenticated.
     *
     * @return a message indicating that a user has successfully authenticated.
     */
    static String       success()
    {
        return localize( "message.success" );
    }

    /**
     * Returns a localized message indicating that a user
     * has logged out.
     *
     * @return a message indicating that a user has logged out.
     */
    static String       logout()
    {
        return localize( "message.logout" );
    }

    /**
     * Returns a localized message indicating that a user
     * has struck out.
     *
     * @return a message indicating that a user has struck out.
     */
    static String       strikeOut()
    {
        return localize( "message.strikeout" );
    }

    /**
     * Returns a localized message indicating that a user
     * has failed to authenticate.
     *
     * @return a message indicating that a user has failed to authenticate.
     */
    static String       failedBecauseDisabled()
    {
        return localize( "message.account.disabled" );
    }

    /**
     * Returns a localized message indicating that a user
     * has failed to authenticate.
     *
     * @return a message indicating that a user has failed to authenticate.
     */
    static String       failedBecauseBadPassword()
    {
        return localize( "message.bad.credential" );
    }

    /**
     * Returns a localized message indicating that a user
     * has failed to authenticate because the account was disabled.
     *
     * @return a message indicating that a user has failed to authenticate.
     */
    static String       failedLogin()
    {
        return localize( "message.failed.login" );
    }

    /**
     * Returns a localized message indicating that a password has expired.
     *
     * @return a message indicating that a password has expired.
     */
    static String       credentialExpired()
    {
        return localize( "message.credential.expired" );
    }

    /**
     * Returns a localized message indicating that a Login has been disabled.
     *
     * @return a message indicating that a Login has been disabled.
     */
    static String       loginDisabled()
    {
        return localize( "message.login.disabled" );
    }

    /**
     * Returns a localized message indicating that the User has no Roles
     * in a Project.
     *
     * @return a message indicating that that the User has no Roles
     *      in a Project.
     */
    static String       noRoles()
    {
        return localize( "message.no.roles" );
    }

    /**
     * Returns a localized message indicating that a password
     *      is of insufficient length.
     *
     * @param requiredLength the required length of a password.
     *
     * @return a localized message indicating that a password
     *      is of insufficient length.
     */
    static String       passwordMinLength( final int requiredLength )
    {
        return localize( "message.password.minlength", requiredLength );
    }

    /**
     * Returns a localized message indicating that a password
     *      is of insufficient length.
     *
     * @param pattern Password pattern
     * @return a localized message indicating that a password
     *      is of insufficient length.
     */
    static String       passwordPattern( final String pattern )
    {
        return localize( "message.password.pattern", pattern );
    }

    /**
     * Returns a localized message indicating that a <code>Map</code>
     * is not a valid representation of Role parameters.
     * @return Localized string
     */
    static String       invalidParameters()
    {
        return localize( "invalid.parameters" );
    }

    //
    // Private
    //

    private static final Object[]   NO_OBJECTS  = new Object[0];
    private static final String     BASIS       = Localize.class.getPackage().getName() + ".Localization";

    /**
     * Localize a simple string message.
     *
     * @param trinket Trinket used to look up the localized message.
     *     Must not be <code>null</code>.
     * @return Localized message.  Will not be <code>null</code>.
     */
    private static String   localize( String trinket )
    {
        return localize( trinket, NO_OBJECTS );
    }

    /**
     * Localize a single argument message.
     *
     * @param trinket Trinket used to look up the localized message.  Must not
     *     be <code>null</code>.
     * @param object Single parameter to the localized message.
     * @return Localized message.  Will not be <code>null</code>.
     */
    private static String   localize( String trinket, Object object )
    {
        return localize( trinket, new Object[] { object } );
    }

    /**
     * Localize a multiple argument message.
     *
     * @param trinket Trinket used to look up the localized message.
     *     Must not be <code>null</code>.
     * @param objects Parameters to the localized message.  Must not be
     *      <code>null</code>.
     * @return Localized message.  Will not be <code>null</code>.
     */
    private static String   localize( String trinket, Object[] objects )
    {
        try
        {
            ResourceBundle messages = ResourceBundle.getBundle(
                BASIS,
                Locale.getDefault(),
                Thread.currentThread().getContextClassLoader()
            );

            String message = messages.getString( trinket );

            return MessageFormat.format( message, objects );
        }
        catch( Exception e )
        {
            try
            {
                StringBuffer message = new StringBuffer();
                message.append( "Localization Failure: trinket=" );
                message.append( trinket );
                message.append( " params=" );

                for( Object object : objects ) message.append( "{" ).append( object ).append( "}" );

                return message.toString();
            }
            catch( Exception ee )
            {
                return "Localization Failure: {error}";
            }
        }
    }
}

